module rgb_to_ycbcr(
	clk				,
	i_r_8b			,
	i_g_8b			,
	i_b_8b			,
	
	i_h_sync			,
	i_v_sync			,
	i_data_en		,

	o_y_8b			,
	o_cb_8b			,
	o_cr_8b			,
	
	o_h_sync			,
	o_v_sync			,
	o_data_en		
);

	input clk;
	input [7:0] i_r_8b;
	input [7:0] i_g_8b;
	input [7:0] i_b_8b;
	
	input i_h_sync;
	input i_v_sync;
	input i_data_en;
	
	output [7:0] o_y_8b ;
	output [7:0] o_cb_8b;
	output [7:0] o_cr_8b;
	
	output o_h_sync;	
	output o_v_sync;	
	output o_data_en;
	
	//multiply 256
	parameter para_0183_10b = 10'd47;  //浮点数转定点数
	parameter para_0614_10b = 10'd157;
	parameter para_0062_10b = 10'd16;
	parameter para_0101_10b = 10'd26;
	parameter para_0338_10b = 10'd86;
	parameter para_0439_10b = 10'd112;
	parameter para_0399_10b = 10'd102;
	parameter para_0040_10b = 10'd10;
	parameter para_16_18b = 18'd4096;  //整数转定点数  18位  小数位8位  两个定点数相乘结果：整数位：m+n 小数位：x+y
	parameter para_128_18b = 18'd32768;
	
	wire sign_cb;
	wire sign_cr;
	
	reg [17:0] mult_r_for_y_18b	;
	reg [17:0] mult_r_for_cb_18b	;
	reg [17:0] mult_r_for_cr_18b	;

	reg [17:0] mult_g_for_y_18b	;
	reg [17:0] mult_g_for_cb_18b	;
	reg [17:0] mult_g_for_cr_18b	;	

	reg [17:0] mult_b_for_y_18b	;
	reg [17:0] mult_b_for_cb_18b	;
	reg [17:0] mult_b_for_cr_18b	;
	
	reg [17:0] add_y_0_18b			;
	reg [17:0] add_cb_0_18b			;
	reg [17:0] add_cr_0_18b			;
	
	reg [17:0] add_y_1_18b			;
	reg [17:0] add_cb_1_18b			;
	reg [17:0] add_cr_1_18b			;
	
	reg[17: 0]  result_y_18b		;
	reg[17: 0]  result_cb_18b		;
	reg[17: 0]  result_cr_18b		;
	
	reg[9:0] y_tmp						;
	reg[9:0] cb_tmp					;
	reg[9:0] cr_tmp					;
	
	reg  i_h_sync_delay_1			;
	reg  i_v_sync_delay_1			;
	reg  i_data_en_delay_1			;
	
	reg  i_h_sync_delay_2			;
	reg  i_v_sync_delay_2			;
	reg  i_data_en_delay_2			;
	
	reg  i_h_sync_delay_3			;
	reg  i_v_sync_delay_3			;
	reg  i_data_en_delay_3			;
	
	
initial begin
	mult_r_for_y_18b	<= 18'd0;
	mult_r_for_cb_18b	<= 18'd0;
	mult_r_for_cr_18b	<= 18'd0;
	
	mult_g_for_y_18b	<= 18'd0; 
	mult_g_for_cb_18b	<= 18'd0; 
	mult_g_for_cr_18b	<= 18'd0;	 
	
	mult_b_for_y_18b	<= 18'd0;
	mult_b_for_cb_18b	<= 18'd0;
	mult_b_for_cr_18b	<= 18'd0;
	
	add_y_0_18b			<= 18'd0;		
	add_cb_0_18b		<= 18'd0;		
	add_cr_0_18b		<= 18'd0;
		
	add_y_1_18b			<= 18'd0;	
	add_cb_1_18b		<= 18'd0;	
	add_cr_1_18b		<= 18'd0;
	
	result_y_18b		<= 18'd0;
    result_cb_18b		<= 18'd0;	
    result_cr_18b		<= 18'd0;
	
	i_h_sync_delay_1	<= 1'd0;
	i_v_sync_delay_1	<= 1'd0;
	i_data_en_delay_1	<= 1'd0;
	
	i_h_sync_delay_2	<= 1'd0;
	i_v_sync_delay_2	<= 1'd0;
	i_data_en_delay_2	<= 1'd0;
	
	end
	
	//LV1 pipeline : mult
	always @ (posedge clk)
		begin
			mult_r_for_y_18b   <=	i_r_8b * 	para_0183_10b;
		    mult_r_for_cb_18b  <= 	i_r_8b *	para_0101_10b;
		    mult_r_for_cr_18b  <= 	i_r_8b * 	para_0439_10b;			
		end
	
	always @ (posedge clk)
		begin
			mult_g_for_y_18b   <=	i_g_8b * para_0614_10b;
			mult_g_for_cb_18b  <= 	i_g_8b *	para_0338_10b;
			mult_g_for_cr_18b  <= 	i_g_8b * para_0399_10b;			
		end	
	
	
	always @ (posedge clk)
		begin
			mult_b_for_y_18b   <=	i_b_8b * para_0062_10b;
		    mult_b_for_cb_18b  <= 	i_b_8b *	para_0439_10b;
		    mult_b_for_cr_18b  <= 	i_b_8b * para_0040_10b;			
		end	
		
	//LV2 pipeline : add
	always @ (posedge clk)
		begin
			add_y_0_18b	 <= mult_r_for_y_18b  +  mult_g_for_y_18b;  //0.183R+0.614G 
			add_cb_0_18b <= mult_b_for_cb_18b +  para_128_18b;      //0.439B+128
			add_cr_0_18b <= mult_r_for_cr_18b +  para_128_18b;      //0.439R+128  正和正相加
			add_y_1_18b	 <= mult_b_for_y_18b  +  para_16_18b;       //0.062B+16
			add_cb_1_18b <= mult_r_for_cb_18b +  mult_g_for_cb_18b; //0.101R+0.338G
			add_cr_1_18b <= mult_g_for_cr_18b +  mult_b_for_cr_18b;	//0.399g+0.04B
		end
		
	//LV3 pipeline : y + cb + cr
	assign  sign_cb = (add_cb_0_18b >= add_cb_1_18b);
	assign  sign_cr = (add_cr_0_18b >= add_cr_1_18b);
	
	always @ (posedge clk )
		begin
			result_y_18b <= add_y_0_18b + add_y_1_18b;
			result_cb_18b <= sign_cb ? (add_cb_0_18b - add_cb_1_18b) : 0;  //负数置零
			result_cr_18b <= sign_cr ? (add_cr_0_18b - add_cr_1_18b) : 0;
		end
		
	always @ (posedge clk)
		begin
			y_tmp		<= result_y_18b[17:8] + {9'd0,result_y_18b[7]};  //补偿精度 如果小数位最高位为1 要将整数位进1
			cb_tmp		<= result_cb_18b[17:8] + {9'd0,result_cb_18b[7]};//补偿精度 如果小数位最高位为1 要将整数位进1
			cr_tmp		<= result_cr_18b[17:8] + {9'd0,result_cr_18b[7]};//补偿精度 如果小数位最高位为1 要将整数位进1
		end
		
	assign o_y_8b  =  	(y_tmp[9:8] == 2'b00) ? y_tmp[7 : 0] : 8'hFF;  //输出的每个颜色通道像素信息是8b 的 这里要进行截取 ，如果最高的前两位有一个1 其代表的整数值都比8'hFF大 所以当高两位有1时 直接取8位全1即可
	assign o_cb_8b =	(cb_tmp[9:8] == 2'b00) ? cb_tmp[7 : 0] : 8'hFF;
	assign o_cr_8b = 	(cr_tmp[9:8] == 2'b00) ? cr_tmp[7 : 0] : 8'hFF;
	
	always @ (posedge clk)  //保持行场同步信号与像素信息同步
		begin
			i_h_sync_delay_1 <= i_h_sync;
			i_v_sync_delay_1 <= i_v_sync;
			i_data_en_delay_1 <= i_data_en;
			i_h_sync_delay_2 <= i_h_sync_delay_1;
			i_v_sync_delay_2 <= i_v_sync_delay_1;
			i_data_en_delay_2 <= i_data_en_delay_1;
			i_h_sync_delay_3 <= i_h_sync_delay_2;
			i_v_sync_delay_3 <= i_v_sync_delay_2;
			i_data_en_delay_3 <= i_data_en_delay_2;
		end
	
	assign  o_h_sync = i_h_sync_delay_3;
	assign  o_v_sync = i_v_sync_delay_3;
	assign  o_data_en = i_data_en_delay_3;	
	
endmodule 